package org.yy;

import org.apache.dubbo.common.constants.CommonConstants;
import org.apache.dubbo.common.extension.Activate;
import org.apache.dubbo.rpc.*;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

@Activate(group = {CommonConstants.CONSUMER, CommonConstants.PROVIDER})
public class TPMonitorFilter implements Filter {

    public static ConcurrentHashMap<String, HashSet<MeInf>> map = new ConcurrentHashMap<>();

    public TPMonitorFilter() {
        PrintDate printDate = new PrintDate();
        //创建执行器 1秒后执行，每隔3秒执行一次
        Executors.newSingleThreadScheduledExecutor().scheduleWithFixedDelay(printDate, 1, 5, TimeUnit.SECONDS);
    }


    @Override
    public Result invoke(Invoker<?> invoker, Invocation invocation) {
        long startTime = System.currentTimeMillis();
        Result invoke = invoker.invoke(invocation);
        long endTime = System.currentTimeMillis();
        long times = endTime - startTime;
        String methodName = invocation.getMethodName();
        MeInf meInf = new MeInf(startTime, endTime, times, methodName);

        addMap(meInf);

        System.out.println("执行了：" + times + "毫秒");
        return invoke;
    }

    void addMap(MeInf meInf) {
        String methodName = meInf.getMethodName();
        HashSet<MeInf> aSet = map.get(methodName);
        if (aSet == null) {
            HashSet<MeInf> set = new HashSet<>();
            set.add(meInf);
            map.put(methodName, set);
        } else {
            aSet.add(meInf);
        }
    }

    class PrintDate implements Runnable {
        @Override
        public void run() {
            LinkedList<MeInf> list = new LinkedList<>();

            for (String key : map.keySet()) {
                HashSet<MeInf> set = map.get(key);
                for (MeInf m : set) {
                    if (m.isLate()) {
                        set.remove(m);
                    } else {
                        list.add(m);
                    }
                }
            }
            //-----------------

            list.sort(new Comparator<MeInf>() {
                @Override
                public int compare(MeInf o1, MeInf o2) {
                    if (o1.getTimes() > o2.getTimes()) {
                        return 1;
                    } else if (o1.getTimes() < o2.getTimes()) {
                        return -1;
                    }
                    return 0;
                }
            });
            int size = list.size();
            double v = size * 0.90;
            double v1 = size * 0.99;

            Long times = list.get((int) v).getTimes();
            Long times1 = list.get((int) v1).getTimes();

            System.out.println(String.format("TP90=%s 毫秒，TP99=%s 毫秒", times, times1));
        }
    }


}
